package 位运算;
/*
给定一个整数数组 nums，其中恰好有两个元素只出现一次，其余所有元素均出现两次。 
找出只出现一次的那两个元素。

示例 :

输入: [1,2,1,3,2,5]
输出: [3,5]
注意：

结果输出的顺序并不重要，对于上面的例子， [5, 3] 也是正确答案。
你的算法应该具有线性时间复杂度。你能否仅使用常数空间复杂度来实现？

 */
public class 只出现一次的数字III {
	/*
	 利用异或，所有数字异或相当于两个不重复的数字异或，结果必不为0，
	 此时，取这个结果中的任意为1的一位，利用这个将原数组分为两类,
	 其中一类是这一位是1的，其中一位是这一位为0的，
	 易知，第一类所有数字的异或为第一个所求数字，第二类所有数字异或为第二个所求数字。
	 */
    public int[] singleNumber(int[] nums) {
        int sum = 0; //记录所有异或的值，即两个只出现一次数的异或
        for (int num:nums) {
        	sum^=num;
		}
        int[] res = new int[2];
        //-sum:在java里存的是其补码
      //sum&-sum:得出两个数异或结果的最右边的一个1，其他的为零，这样进行&操作就可以将两个不同的数分到不同的两组去
        sum &= -sum;    
        for(int i=0;i<nums.length;i++){
            if((sum&nums[i])==0) {//sum中为1位为0的，会找到5
            	res[0] ^= nums[i];
            }else  {//sum中为1位为1的，会找到3
                res[1] ^=nums[i];
            }
        }
        return res;
    }
    
}
